package indigo.ueditor;

import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;

public class UEditorController {
	private static final String CALLBACK_PATTERN = "^[a-zA-Z_]+[\\w0-9_]*$";

	private final ObjectMapper objectMapper = new ObjectMapper();

	private final Map<String, UEditorHandler> handlerMap;

	public UEditorController(List<UEditorHandler> handlers) {
		Map<String, UEditorHandler> handlerMap = Maps.newHashMap();
		for (UEditorHandler handler : handlers) {
			handlerMap.put(handler.getName(), handler);
		}
		this.handlerMap = ImmutableMap.copyOf(handlerMap);
	}

	@RequestMapping(path = "/controller", params = { "action" })
	public ResponseEntity<?> controller(
			HttpServletRequest request,
			@RequestParam("action") String action,
			@RequestParam(name = "callback", required = false) String callback) throws JsonProcessingException {
		Object result;
		try {
			if (callback != null && !callback.matches(CALLBACK_PATTERN)) {
				throw new UEditorException(UEditorState.ILLEGAL);
			}
			UEditorHandler handler = handlerMap.get(action);
			if (handler == null) {
				throw new UEditorException(UEditorState.INVALID_ACTION);
			}
			result = handler.handle(request);
		} catch (UEditorException e) {
			result = Collections.singletonMap("state", e.getState().getMessage());
		}
		String body = objectMapper.writeValueAsString(result);
		if (callback != null) {
			return ResponseEntity.ok().body(String.format("%s(%s)", callback, body));
		} else {
			return ResponseEntity.ok().body(body);
		}
	}
}
